package com.zyf.system.controller;

import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.zyf.system.controller.dto.ScheduleAddDto;
import com.zyf.system.controller.dto.SchedulePageDto;
import com.zyf.system.controller.dto.ScheduleUpdateDto;
import com.zyf.system.db.mysql.QDoctor;
import com.zyf.system.db.mysql.QSchedule;
import com.zyf.system.db.mysql.QUser;
import com.zyf.system.db.mysql.Schedule;
import com.zyf.system.repository.DoctorRepository;
import com.zyf.system.repository.ScheduleRepository;
import com.zyf.system.repository.UserRepository;
import com.zyf.system.until.Constant;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 张云帆
 * 2025/4/2 11:10
 */
@RestController
@RequestMapping("/schedule")
public class ScheduleController extends BaseController{
    @Autowired
    private ScheduleRepository scheduleRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private DoctorRepository doctorRepository;
    private final QSchedule qSchedule = QSchedule.schedule;
    private final QUser qUser = QUser.user;
    private final QDoctor qDoctor = QDoctor.doctor;

    @PostMapping("/page")
    @ApiOperation(value = "分页查询排班信息", notes = "分页查询排班信息")
    public Map<String, Object> page(SchedulePageDto schedulePageDto) {
        try {
            Pageable pageable = PageRequest.of(schedulePageDto.getPageNum() - 1, schedulePageDto.getPageSize());
            Predicate schedulePredicate = qSchedule.isDeleted.isFalse();
            if(schedulePageDto.getDoctorName() != null && !schedulePageDto.getDoctorName().isEmpty()){
                Predicate userPredicate = qUser.realName.like("%" + schedulePageDto.getDoctorName() + "%");
                List<Integer> userIdList = new ArrayList<>();
                userRepository.findAll(userPredicate).forEach(user -> userIdList.add(user.getId()));
                List<Integer> doctorIdList = new ArrayList<>();
                doctorRepository.findAll(qDoctor.userId.in(userIdList)).forEach(doctor -> doctorIdList
                        .add(doctor.getId()));
                if(!doctorIdList.isEmpty()){
                    schedulePredicate = ExpressionUtils.and(schedulePredicate,qSchedule.doctorId.in(doctorIdList));
                }
            }
            if(schedulePageDto.getDepartmentId() != null){
                schedulePredicate = ExpressionUtils.and(schedulePredicate,qSchedule.departmentId
                        .eq(schedulePageDto.getDepartmentId()));
            }
            if(schedulePageDto.getStartTimeBegin() != null){
                schedulePredicate = ExpressionUtils.and(schedulePredicate, qSchedule.startTime
                        .after(schedulePageDto.getStartTimeBegin()));
            }
            if(schedulePageDto.getStartTimeEnd() != null){
                schedulePredicate = ExpressionUtils.and(schedulePredicate, qSchedule.startTime
                        .before(schedulePageDto.getStartTimeEnd()));
            }
            if(schedulePageDto.getEndTimeBegin() != null){
                schedulePredicate = ExpressionUtils.and(schedulePredicate, qSchedule.endTime
                        .after(schedulePageDto.getEndTimeBegin()));
            }
            if(schedulePageDto.getEndTimeEnd() != null){
                schedulePredicate = ExpressionUtils.and(schedulePredicate, qSchedule.endTime
                        .before(schedulePageDto.getEndTimeEnd()));
            }
            return createResponse(Constant.SUCCESS, "分页查询排班信息成功", scheduleRepository
                    .findAll(schedulePredicate, pageable));
        }catch (Exception e){
            return createResponse(Constant.FAIL, "分页查询排班信息异常", e.getMessage());
        }
    }

    @PostMapping("/add")
    @ApiOperation(value = "添加排班信息", notes = "添加排班信息")
    public Map<String, Object> add(@Validated @RequestBody ScheduleAddDto scheduleAddDto) {
        try {
            if(!scheduleRepository.exists(qSchedule.doctorId.eq(scheduleAddDto.getDoctorId()))){
                return createResponse(Constant.FAIL, "医生不存在", null);
            }
            if(scheduleRepository.exists(qSchedule.departmentId.eq(scheduleAddDto.getDepartmentId()))){
                return createResponse(Constant.FAIL, "科室不存在", null);
            }
            if(scheduleRepository.exists(qSchedule.doctorId.eq(scheduleAddDto.getDoctorId())
                    .and(qSchedule.startTime.between(scheduleAddDto.getStartTime(), scheduleAddDto.getEndTime())
                            .or(qSchedule.endTime.between(scheduleAddDto.getStartTime(), scheduleAddDto.getEndTime())))
                    .and(qSchedule.startTime.before(scheduleAddDto.getStartTime())
                            .and(qSchedule.endTime.after(scheduleAddDto.getEndTime()))))){
                return createResponse(Constant.FAIL, "该医生在该时间段内已有排班信息", null);
            }
            return createResponse(Constant.SUCCESS, "添加排班信息成功", scheduleRepository.save(new Schedule(scheduleAddDto)));
        }catch (Exception e){
            return createResponse(Constant.FAIL, "添加排班信息异常", e.getMessage());
        }
    }

    @PostMapping("/update")
    @ApiOperation(value = "修改排班信息", notes = "修改排班信息")
    public Map<String, Object> update(@Validated @RequestBody ScheduleUpdateDto scheduleUpdateDto) {
        try {
            Schedule schedule = scheduleRepository.findById(scheduleUpdateDto.getId()).orElse(null);
            if(schedule == null) {
                return createResponse(Constant.FAIL, "排班信息不存在", null);
            }
            if(!scheduleRepository.exists(qSchedule.doctorId.eq(scheduleUpdateDto.getDoctorId()))){
                return createResponse(Constant.FAIL, "医生不存在", null);
            }
            if(scheduleRepository.exists(qSchedule.departmentId.eq(scheduleUpdateDto.getDepartmentId()))){
                return createResponse(Constant.FAIL, "科室不存在", null);
            }
            if(scheduleRepository.exists(qSchedule.doctorId.eq(scheduleUpdateDto.getDoctorId())
                    .and(qSchedule.startTime.between(scheduleUpdateDto.getStartTime(), scheduleUpdateDto.getEndTime())
                            .or(qSchedule.endTime.between(scheduleUpdateDto.getStartTime(), scheduleUpdateDto.getEndTime())))
                    .and(qSchedule.startTime.before(scheduleUpdateDto.getStartTime())
                            .and(qSchedule.endTime.after(scheduleUpdateDto.getEndTime())))
                    .and(qSchedule.id.ne(scheduleUpdateDto.getId())))){
                return createResponse(Constant.FAIL, "该医生在该时间段内已有排班信息", null);
            }
            if(scheduleUpdateDto.getMaxPatients() != null){
                schedule.setMaxPatients(scheduleUpdateDto.getMaxPatients());
            }
            if(scheduleUpdateDto.getCurrentPatients() != null){
                schedule.setCurrentPatients(scheduleUpdateDto.getCurrentPatients());
            }
            schedule.setDoctorId(scheduleUpdateDto.getDoctorId());
            schedule.setDepartmentId(scheduleUpdateDto.getDepartmentId());
            schedule.setStartTime(scheduleUpdateDto.getStartTime());
            schedule.setEndTime(scheduleUpdateDto.getEndTime());
            return createResponse(Constant.SUCCESS, "修改排班信息成功", scheduleRepository.save(schedule));
        }catch (Exception e){
            return createResponse(Constant.FAIL, "修改排班信息异常", e.getMessage());
        }
    }

    @DeleteMapping("/delete")
    @ApiOperation(value = "删除排班信息", notes = "删除排班信息")
    public Map<String, Object> delete(@Validated @RequestParam Integer id) {
        try {
            Schedule schedule = scheduleRepository.findById(id).orElse(null);
            if(schedule == null) {
                return createResponse(Constant.FAIL, "排班信息不存在", null);
            }
            scheduleRepository.delete(schedule);
            return createResponse(Constant.SUCCESS, "删除排班信息成功", null);
        }catch (Exception e){
            return createResponse(Constant.FAIL, "删除排班信息异常", e.getMessage());
        }
    }

    @DeleteMapping("/deleteBatch")
    @ApiOperation(value = "批量删除排班信息", notes = "批量删除排班信息")
    public Map<String, Object> deleteBatch(@Validated @RequestParam String ids) {
        try {
            List<Integer> idList = Arrays.stream(ids.split(",")).map(Integer::parseInt).collect(Collectors.toList());
            List<Schedule> scheduleList = scheduleRepository.findAllById(idList);
            for (Schedule schedule : scheduleList) {
                if(schedule == null) {
                    return createResponse(Constant.FAIL, "排班信息不存在", null);
                }
            }
            scheduleRepository.deleteAll(scheduleList);
            return createResponse(Constant.SUCCESS,"批量删除排班信息成功", null);
        }catch (Exception e){
            return createResponse(Constant.FAIL, "批量删除排班信息异常", e.getMessage());
        }
    }

    @GetMapping("/get")
    @ApiOperation(value = "查询排班信息", notes = "查询排班信息")
    public Map<String, Object> get(@Validated @RequestParam Integer id) {
        try {
            Schedule schedule = scheduleRepository.findById(id).orElse(null);
            if(schedule == null) {
                return createResponse(Constant.FAIL, "排班信息不存在", null);
            }
            return createResponse(Constant.SUCCESS, "查询排班信息成功", schedule);
        }catch (Exception e){
            return createResponse(Constant.FAIL, "查询排班信息异常", e.getMessage());
        }
    }
}
